from flask import Blueprint, request, jsonify, Response, stream_with_context
from services.indicator_agent_service import IndicatorAgentService
from services.chroma_service import ChromaService
from services.indicator_routes_service import IndicatorRoutesService
from agents.text2sql import Text2SQLAgent
from typing import Dict, Any
import json
import asyncio
import jieba
from services.intent_recognition_service import IntentRecognitionService
import pymysql.cursors
from services.conversation_service import ConversationService, SessionService
#from utils.date_transformer import transform_json
from models.sessions import EventType


indicator_bp = Blueprint('indicator', __name__)
indicator_service = IndicatorAgentService()
indicator_routes_service = IndicatorRoutesService()
text2sql_agent = Text2SQLAgent()
chroma_service = ChromaService()
intent_service = IntentRecognitionService()

@indicator_bp.route('/process-query', methods=['POST'])
def process_indicator_query():
    """
    处理指标查询的API端点
    
    请求体格式:
    {
        "query": "查询文本",
        "dark_mode": false  // 可选，默认为false
    }
    
    返回:
    {
        "parsed_result": object,
        "match_result": object,
        "dimensions": array,
        "filters": array,
        "query_params": object,
        "data": array,
        "plot_code": object,
        "figure": object,
        "status": "success" | "error",
        "message": string
    }
    """
    try:
        data = request.get_json()
        if not data or 'query' not in data:
            return jsonify({
                'status': 'error',
                'message': '缺少必要的查询参数'
            }), 400
        if 'permission_check' in data and not isinstance(data['permission_check'], bool):
            return jsonify({
                'status': 'error',
                'message': 'permission_check参数必须是布尔类型'
            }), 400
        if 'permission_check' in data and data['permission_check'] and 'user_id' not in data:
            return jsonify({
                'status': 'error',
                'message': '开启认证时，必须提供user_id参数'
            }), 400

        query = data['query']
        user_id = data.get('user_id')
        dark_mode = data.get('dark_mode', False)
        permission_check = data.get('permission_check', True)

        result = indicator_service.process_indicator_query(query, user_id, dark_mode, permission_check)
        
        # 检查数据类型并进行相应的转换
        if result.get('data') is not None:
            if hasattr(result['data'], 'to_dict'):  # 如果是DataFrame
                result['data'] = result['data'].to_dict(orient='records')
            # 如果已经是list就不需要转换
            
        # 如果结果包含Plotly图形，将其转换为JSON
        if result.get('figure') is not None:
            result['figure'] = result['figure'].to_json()

        return jsonify(result)

    except Exception as e:
        return jsonify({
            'status': 'error',
            'message': f'处理请求时发生错误: {str(e)}'
        }), 500

@indicator_bp.route('/process-query-stream', methods=['POST'])
def query_indicators_stream():
    try:
        data = request.get_json()
        if not data or 'query' not in data:
            return jsonify({
                'status': 'error',
                'message': '缺少必要的查询参数'
            }), 400
        if 'permission_check' in data and not isinstance(data['permission_check'], bool):
            return jsonify({
                'status': 'error',
                'message': 'permission_check参数必须是布尔类型'
            }), 400
        if 'permission_check' in data and data['permission_check'] and 'user_id' not in data:
            return jsonify({
                'status': 'error',
                'message': '开启认证时，必须提供user_id参数'
            }), 400

        query = data['query']
        user_id = data.get('user_id')
        dark_mode = data.get('dark_mode', False)
        permission_check = data.get('permission_check', False)
        type = data.get('type', "indicator")

        # 获取或创建会话
        conversation_service = ConversationService()
        session_service = SessionService()
        session_id = data.get('session_id')
        history_messages = []
        if not session_id:
            # 创建新会话
            session_id = conversation_service.create_session(user_id, query, EventType.METRICS_INQUERY)
        else:
            # 获取会话历史记录
            history_messages = conversation_service.get_conversation_history(session_id)
        # 创建新的对话记录并获取conversation_id
        conversation_id = conversation_service.add_conversation(
            session_id=session_id,
            user_query=query,
            response="",  # 初始响应为空
            key_info=""
        )
        def generate():
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)

            async def process_stream():
                stream_method = (text2sql_agent.text2sql_stream 
                               if type == "text2sql" 
                               else indicator_service.process_indicator_query_stream)
                
                async for result in stream_method(query, user_id, dark_mode, permission_check, history_messages):
                    result_copy = result.copy()
                    # 将会话ID添加到结果中
                    result_copy['session_id'] = session_id
                    result_copy['conversation_id'] = conversation_id
                    # 处理 data 与 figure 的转换
                    if 'data' in result_copy and result_copy['data'] is not None:
                        if hasattr(result_copy['data'], 'to_dict'):
                            result_copy['data'] = result_copy['data'].to_dict(orient='records')
                    if result_copy.get('figure') is not None:
                        result_copy['figure'] = result_copy['figure'].to_json()

                    # 检查是否需要对文本内容进行切分，产生打字机效果
                    if result_copy.get('split'):  # 例如：{"split": true, "text": "要切分的内容"}
                        content = result_copy.get('think', '')
                        if not content:
                            # 如果没有需要切分的文本，则直接返回原 JSON
                            yield f"data: {json.dumps(result_copy, ensure_ascii=False)}\n\n"
                        else:
                            # 使用 jieba 进行中文分词
                            tokens = jieba.lcut(content)
                            status = result_copy.get('status', None)
                            step = result_copy.get('step', None)
                            for token in tokens:
                                yield f"data: {json.dumps({'status': status, 'step': step, 'think': token}, ensure_ascii=False)}\n\n"
                                # 延时模拟打字机效果，可根据需要调整时间
                                await asyncio.sleep(0.1)
                    else:
                        # 如果不需要切分，直接返回整个 JSON 对象
                        yield f"data: {json.dumps(result_copy, ensure_ascii=False)}\n\n"

                # 保存对话记录
                # 根据 type 字段决定保存内容
                response_to_save = ""
                result_type = result_copy.get("type")
                if result_type == "indicator":
                    response_to_save = json.dumps(result_copy.get("query_params", ""), ensure_ascii=False)
                elif result_type == "text2sql":
                    #response_to_save = json.dumps(result_copy.get("sql", ""), ensure_ascii=False)
                    response_to_save = result_copy.get("sql", "")
                print(f"当前 result_type: {result_type}")
                # 映射 result_type 为 EventType 枚举值
                if result_type == "text2sql":
                    event_type_enum = EventType.TEXT2SQL  # 注意拼写：是 EventType.TEXT2SQl
                elif result_type == "indicator":
                    event_type_enum = EventType.METRICS_INQUERY
                else:
                    event_type_enum = EventType.UNKNOWN
                #更新session
                session_service.update_session(
                    session_id=session_id,
                    initial_query=query,
                      event_type=event_type_enum
                )

                # 使用conversation_id更新对话记录
                conversation_service.update_conversation(
                    conversation_id=conversation_id,
                    response=json.dumps(result_copy, ensure_ascii=False),
                    key_info=response_to_save
                )
            async def stream_generator():
                async for item in process_stream():
                    yield item

            agen = stream_generator()
            try:
                while True:
                    try:
                        item = loop.run_until_complete(agen.__anext__())
                        yield item
                    except StopAsyncIteration:
                        break
            finally:
                loop.close()
                conversation_service.close()

        return Response(
            stream_with_context(generate()),
            mimetype='text/event-stream',
            headers={
                'Cache-Control': 'no-cache',
                'Connection': 'keep-alive',
                'X-Accel-Buffering': 'no'
            }
        )

    except Exception as e:
        return jsonify({'error': str(e)}), 500
@indicator_bp.route('/process-query-change', methods=['POST'])
def process_query_change():
    """
    处理指标查询的API端点
    
    请求体格式:
    {
        "indicator": "指标代码",          // 必填，指标的唯一标识代码
        "indicator_desc": "指标名称",     // 可选，指标的显示名称
        "dimension": "维度代码",          // 必填，维度的唯一标识代码
        "dimension_desc": "维度名称",     // 可选，维度的显示名称
        "startDate": "2024-01-01",       // 必填，查询开始日期，格式：YYYY-MM-DD
        "endDate": "2024-03-01",          // 必填，查询结束日期，格式：YYYY-MM-DD
        "permission_check": false,      // 可选，是否进行权限检查，默认不检查
        "user_id": "user123"           // 可选，用户ID，仅在 permission_check 为 true 时需要
    }
    
    返回:
    {
        'result': query_result,
        'status': 'success',
        'message': ""
    }
    """
    try:
        data = request.get_json()
        return indicator_routes_service.handle_indicator_query(data)
    except Exception as e:
        print(f"查询失败: {e}")
        return jsonify({'status': 'error', 'message': ''}), 500


@indicator_bp.route('/query_dimension_values', methods=['POST'])
def query_dimension_values():
    """
    根据维度编码、维度名称和关键字，从向量库的码表中查询维度值（默认最多返回10条）
    请求体示例:
    {
        "dimension_code": "Doc",
        "dimension_name": "医生信息",
        "key": "李",
        "limit": 10
    }
    返回:
    {
        "status": "success",
        "data": [
            {"code": "D001", "desc": "李四"},
            ...
        ]
    }
    """
    try:
        data = request.get_json()
        result, status_code = indicator_routes_service.find_dimension_values(data)  
        return jsonify(result), status_code
    except Exception as e:
        print(f"[query_dimension_values] 查询失败: {e}")
        return jsonify({'status': 'error', 'message': str(e)}), 500

@indicator_bp.route('/recognize-intent', methods=['POST'])
def recognize_intent():
    """
    用户意图识别接口
    请求体: {"query": "用户输入内容"}
    返回: {"Text-Search": ...} 或 {"Metrics-Inquery": ...} 或 {"Unknown": ...}
    """
    try:
        data = request.get_json()
        if not data or 'query' not in data:
            return jsonify({'status': 'error', 'message': '缺少 query 参数'}), 400
        user_query = data['query']
        result = intent_service.recognize_intent(user_query)
        return jsonify(result)
    except Exception as e:
        return jsonify({'status': 'error', 'message': str(e)}), 500
    
@indicator_bp.route('/indicator_values', methods=['POST'])
def indicator_values():
    data = request.get_json()
    indicator = data.get('indicator')
    if not indicator:
        return {"error": "指标代码 missing!"}, 400

    print(f"查询指标代码: {indicator}")
    result_data = indicator_routes_service.find_indicators_values(indicator)
    return {"data": result_data, "status": "success"}